﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.BlackApart.Business.Apartments;
using blackhouse.BlackApart.Business.Opinions;

namespace blackhouse.BlackApart.Business {
	public class ApartmentSortModel {

		#region Fields

		protected Dictionary<string, Sorter> sorters = new Dictionary<string, Sorter>();

		#endregion

		#region Properties

		public virtual string SortBy { get; set; }
		public virtual SortDirection Direction { get; set; }

		#endregion

		#region Inner

		public delegate IEnumerable<IApartmentGroup> SortApartment(IEnumerable<IApartmentGroup> apartments);

		public enum SortDirection { Asc = 1, Desc = 2 }

		protected class Sorter {
			public SortApartment SorterDel;
			public string Name;
			public string Key;
			public SortDirection DefaultSort = SortDirection.Asc;
		}

		#endregion

		#region Methods

		public void AddSorter(string key, string name, SortApartment sorter) {
			this.AddSorter(key, name, sorter, SortDirection.Asc);
		}

		public void AddSorter(string key, string name, SortApartment sorter, SortDirection direction) {
			Sorter s = new Sorter();
			s.Key = key;
			s.Name = name;
			s.SorterDel = sorter;
			s.DefaultSort = direction;

			if (this.sorters.ContainsKey(key))
				this.sorters[key] = s;
			else
				this.sorters.Add(key, s);
		}

		public void AddDefaultSorterByName() {
			this.AddDefaultSorterByName("Nazwa");
		}

		public void AddDefaultSorterByName(string name) {
			this.AddSorter("name", name, SortByName);
		}

		public void AddDefaultSorterByOpinions() {
			this.AddDefaultSorterByOpinions("Ocen");
		}

		public void AddDefaultSorterByOpinions(string name) {
			this.AddSorter("opinions", name, SortByOpinions, SortDirection.Desc);
		}

		public void AddDefaultSorterByPopularity() {
			this.AddDefaultSorterByPopularity("Popularności");
		}

		public void AddDefaultSorterByPopularity(string name) {
			this.AddSorter("popularity", name, SortByPopularity, SortDirection.Desc);
		}

		public IEnumerable<IApartmentGroup> Sort(IEnumerable<IApartmentGroup> groups) {
			if (sorters.ContainsKey(this.SortBy))
				groups = sorters[this.SortBy].SorterDel(groups);
			if (this.Direction == SortDirection.Desc)
				groups = groups.Reverse();
			return groups;
		}

		private IEnumerable<IApartmentGroup> SortByName(IEnumerable<IApartmentGroup> groups) {
			return groups.OrderBy(a => a.ShortName);
		}

		private IEnumerable<IApartmentGroup> SortByOpinions(IEnumerable<IApartmentGroup> groups) {
			StatisticsOpinion so = Factory.Instance().GetStatisticsOpinion();
			var q = from g in groups
					select new { Group = g, avg = so.GetAverageRating(g.Id) };

			return q.OrderBy(qi => qi.avg).Select(qi => qi.Group);
		}

		private IEnumerable<IApartmentGroup> SortByPopularity(IEnumerable<IApartmentGroup> groups) {
			return groups.OrderBy(a => a.Popularity);
		}

		#endregion

	}
}
